/******************************************************************************
*
* This file is part of FreeTrack (http://code.google.com/p/qtfreetrack).
* BY Willy Gardiol (willy@gardiol.org)
*
* FreeTrack is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeTrack is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/

#include "layermapconfig.h"
#include "layermapcalibrate.h"
#include "layermap.h"
#include "filenavigator.h"
#include "ftpushbutton.h"
#include "ftlabel.h"
#include "fttabwidget.h"

#include "trackgps.h"

extern TrackGps* gps;

LayerMapConfig::LayerMapConfig(QWidget* parent, LayerMap *layer) :
    FreeTrackWidget(parent),
    layer_map(layer)
{
    connect( layer_map, SIGNAL( redraw() ),
                  this, SLOT( update() ) );

    QList<QPoint> xy;
    QList<QPointF> ll;
    layer_map->getPointsLL( ll );
    layer_map->getPointsXY( xy );

    // Create tabs..
    tabs = new FTTabWidget();

    // setup tab
    tab_setup = new QWidget();
    title_label = new FTLabel( tr("Track title:"));
    title = new QLineEdit( layer_map->getTitle() );
    description_label = new FTLabel( tr("Track description:"));
    description = new QLineEdit( layer_map->getDescription() );
    import_ozical = new FTPushButton( QIcon(":/icons/ozi.png"), BUTTON_SIZE);
    import_ozical->setText( tr("Import calibration"));
    connect( import_ozical, SIGNAL(clicked()),
             this, SLOT( importCalibration() ));
    clear_cache = new FTPushButton( QIcon(":/icons/clear_cache.png"), BUTTON_SIZE);
    clear_cache->setText( tr("Clear map cache") );
    connect( clear_cache, SIGNAL(clicked()),
             this, SLOT( clearCache() ));
    rebuild_cache = new FTPushButton( QIcon(":/icons/rebuild_cache.png"), BUTTON_SIZE);
    rebuild_cache->setText( tr("Rebuild map cache"));
    connect( rebuild_cache, SIGNAL(clicked()),
             this, SLOT( rebuildCache() ));


    // Map tab
    calibrator = new LayerMapCalibrate(layer_map);
    connect( calibrator, SIGNAL(pointChanged(int,QPoint)),
                   this, SLOT( updateMapPt(int,QPoint)));
    connect( this, SIGNAL(updatePoint(int,QPoint)),
             calibrator, SLOT(updatePoint(int,QPoint)));

    // Points tab
    pointsTab = new QWidget();
    point1_label = new FTLabel(tr("Point n.1"));
    point1_getgps = new FTPushButton( QIcon(":/icons/gps_ant.png"), ICON_SIZE_24);
    connect( point1_getgps, SIGNAL(clicked()),
                     this, SLOT(updateCoord1()));
    point1_x_label = new FTLabel("x");
    point1_x = new QLineEdit( QString("%1").arg( xy.at(0).x()));
    connect( point1_x, SIGNAL(textChanged(QString)),
                this, SLOT(updateUserPt1(QString)) );
    point1_y_label = new FTLabel("y");
    point1_y = new QLineEdit( QString("%1").arg( xy.at(0).y()));
    connect( point1_y, SIGNAL(textChanged(QString)),
                this, SLOT(updateUserPt1(QString)) );
    point1_lat_label = new FTLabel(tr("Lat:"));
    point1_lat = new QLineEdit( QString("%1").arg( ll.at(0).y()));
    point1_lon_label = new FTLabel(tr("Lon:"));
    point1_lon = new QLineEdit( QString("%1").arg( ll.at(0).x()));

    point2_label = new FTLabel(tr("Point n.2"));
    point2_getgps = new FTPushButton( QIcon(":/icons/gps_ant.png"), ICON_SIZE_24);
    connect( point2_getgps, SIGNAL(clicked()),
                     this, SLOT(updateCoord2()));
    point2_x_label = new FTLabel("x");
    point2_x = new QLineEdit( QString("%1").arg( xy.at(1).x()));
    connect( point2_x, SIGNAL(textChanged(QString)),
                this, SLOT(updateUserPt2(QString)) );
    point2_y_label = new FTLabel("y");
    point2_y = new QLineEdit( QString("%1").arg( xy.at(1).y()));
    connect( point2_y, SIGNAL(textChanged(QString)),
                this, SLOT(updateUserPt2(QString)) );
    point2_lat_label = new FTLabel(tr("Lat:"));
    point2_lat = new QLineEdit( QString("%1").arg( ll.at(1).y()));
    point2_lon_label = new FTLabel(tr("Lon:"));
    point2_lon = new QLineEdit( QString("%1").arg( ll.at(1).x()));

    point3_label = new FTLabel(tr("Point n.3"));
    point3_getgps = new FTPushButton( QIcon(":/icons/gps_ant.png"), ICON_SIZE_24);
    connect( point3_getgps, SIGNAL(clicked()),
                     this, SLOT(updateCoord3()));
    point3_x_label = new FTLabel("x");
    point3_x = new QLineEdit( QString("%1").arg( xy.at(2).x()));
    connect( point3_x, SIGNAL(textChanged(QString)),
                this, SLOT(updateUserPt3(QString)) );
    point3_y_label = new FTLabel("y");
    point3_y = new QLineEdit( QString("%1").arg( xy.at(2).y()));
    connect( point3_y, SIGNAL(textChanged(QString)),
                this, SLOT(updateUserPt3(QString)) );
    point3_lat_label = new FTLabel(tr("Lat:"));
    point3_lat = new QLineEdit( QString("%1").arg( ll.at(2).y()));
    point3_lon_label = new FTLabel(tr("Lon:"));
    point3_lon = new QLineEdit( QString("%1").arg( ll.at(2).x()));

    tabs->addTab( tab_setup, tr("Setup"));
    tabs->addTab( calibrator, tr("Calibrate"));
    tabs->addTab( pointsTab, tr("Set points"));

    // Save and cancel buttons
    save_button = new FTPushButton( QIcon( ":/icons/save.png"), BUTTON_SIZE);
    connect( save_button, SIGNAL(clicked()),
             this, SLOT(updateMap()) );
    cancel_button = new FTPushButton( QIcon( ":/icons/cancel.png"), BUTTON_SIZE);
    connect( cancel_button, SIGNAL(clicked()),
             this, SIGNAL(accept()));

    QWidget* bts = new QWidget();
    QHBoxLayout* hgrid = new QHBoxLayout(bts);
    hgrid->addStretch();
    hgrid->addWidget( save_button );
    hgrid->addStretch();
    hgrid->addWidget( cancel_button );
    hgrid->addStretch();
    tabs->addExtra( bts );

}

void LayerMapConfig::updateMapPt(int p, QPoint pt)
{
    if ( p == 1 )
    {
        point1_x->setText( QString("%1").arg(pt.x()));
        point1_y->setText( QString("%1").arg(pt.y()));
    }
    else if ( p == 2 )
    {
        point2_x->setText( QString("%1").arg(pt.x()));
        point2_y->setText( QString("%1").arg(pt.y()));
    }
    else if ( p == 3 )
    {
        point3_x->setText( QString("%1").arg(pt.x()));
        point3_y->setText( QString("%1").arg(pt.y()));
    }
}

void LayerMapConfig::updateUserPt1(QString d)
{
    int x = point1_x->text().toInt();
    int y = point1_y->text().toInt();
    emit updatePoint(1, QPoint(x, y));
}

void LayerMapConfig::updateUserPt2(QString d)
{
    int x = point2_x->text().toInt();
    int y = point2_y->text().toInt();
    emit updatePoint(2, QPoint(x, y));
}

void LayerMapConfig::updateUserPt3(QString d)
{
    int x = point3_x->text().toInt();
    int y = point3_y->text().toInt();
    emit updatePoint(3, QPoint(x, y));
}

void LayerMapConfig::clearCache()
{
    if ( QMessageBox::question( this,
                             tr("Clear map cache"),
                             tr("Really clear map cache?"),
                             QMessageBox::Yes|QMessageBox::No,
                             QMessageBox::NoButton ) == QMessageBox::Yes )
    {
        layer_map->clearCache();
    }
}

void LayerMapConfig::rebuildCache()
{
    if ( QMessageBox::question( this,
                             tr("Rebuild map cache"),
                             tr("Really rebuild map cache?"),
                             QMessageBox::Yes|QMessageBox::No,
                             QMessageBox::NoButton ) == QMessageBox::Yes )
    {
        layer_map->cacheRebuild();
    }
}

void LayerMapConfig::updateCoord1()
{
    if ( QMessageBox::question( this,
                             tr("Update point 1"),
                             tr("Use current position for Point 1?"),
                             QMessageBox::Yes|QMessageBox::No,
                             QMessageBox::NoButton ) == QMessageBox::Yes )
    {
        QPointF ptF = gps->currentPosition();
        point1_lat->setText( QString("%1").arg(ptF.y()));
        point1_lon->setText( QString("%1").arg(ptF.x()));
    }
}

void LayerMapConfig::updateCoord2()
{
    if ( QMessageBox::question( this,
                             tr("Update point 2"),
                             tr("Use current position for Point 2?"),
                             QMessageBox::Yes|QMessageBox::No,
                             QMessageBox::NoButton ) == QMessageBox::Yes )
    {
        QPointF ptF = gps->currentPosition();
        point2_lat->setText( QString("%1").arg(ptF.y()));
        point2_lon->setText( QString("%1").arg(ptF.x()));
    }
}

void LayerMapConfig::updateCoord3()
{
    if ( QMessageBox::question( this,
                             tr("Update point 3"),
                             tr("Use current position for Point 3?"),
                             QMessageBox::Yes|QMessageBox::No,
                             QMessageBox::NoButton ) == QMessageBox::Yes )
    {
        QPointF ptF = gps->currentPosition();
        point3_lat->setText( QString("%1").arg(ptF.y()));
        point3_lon->setText( QString("%1").arg(ptF.x()));
    }
}

void LayerMapConfig::updateMap()
{
    if ( layer_map->getTitle() != title->text() )
        layer_map->setTitle( title->text() );

    if ( layer_map->getDescription() != description->text() )
        layer_map->setDescription( description->text() );

    QList<QPoint> xy;
    xy.append( QPoint( point1_x->text().toDouble(), point1_y->text().toDouble() ) );
    xy.append( QPoint( point2_x->text().toDouble(), point2_y->text().toDouble() ) );
    xy.append( QPoint( point3_x->text().toDouble(), point3_y->text().toDouble() ) );
    QList<QPointF> ll;
    ll.append( QPointF( point1_lon->text().toDouble(), point1_lat->text().toDouble() ) );
    ll.append( QPointF( point2_lon->text().toDouble(), point2_lat->text().toDouble() ) );
    ll.append( QPointF( point3_lon->text().toDouble(), point3_lat->text().toDouble() ) );
    layer_map->setPoints( xy, ll );
    // save calibration is called automatically

    emit accept();
}


QLayout* LayerMapConfig::createHorizontal()
{
    QHBoxLayout* grid = new QHBoxLayout();
    // setup tab
    if ( tab_setup->layout() )
        delete tab_setup->layout();
    QVBoxLayout* setupGrid = new QVBoxLayout();
    setupGrid->addWidget( title_label );
    setupGrid->addWidget( title );
    setupGrid->addWidget( description_label );
    setupGrid->addWidget( description );
 //   QHBoxLayout* btGrid = new QHBoxLayout();
    setupGrid->addWidget( import_ozical );
    setupGrid->addWidget( clear_cache );
    setupGrid->addWidget( rebuild_cache );
//    setupGrid->addLayout( btGrid );
    setupGrid->addStretch();
    tab_setup->setLayout( setupGrid );

    // points tab
    if ( pointsTab->layout() )
        delete pointsTab->layout();
    QVBoxLayout* ptGrid = new QVBoxLayout();
    QHBoxLayout* ptlGrid = new QHBoxLayout();
    ptlGrid->addWidget( point1_label,2 );
    ptlGrid->addWidget( point1_getgps );
    ptGrid->addLayout( ptlGrid );
    QHBoxLayout* xyGrid = new QHBoxLayout();
    xyGrid->addWidget( point1_x_label );
    xyGrid->addWidget( point1_x );
    xyGrid->addWidget( point1_y_label );
    xyGrid->addWidget( point1_y );
    ptGrid->addLayout( xyGrid );
    QHBoxLayout* llGrid = new QHBoxLayout();
    llGrid->addWidget( point1_lat_label );
    llGrid->addWidget( point1_lat );
    ptGrid->addLayout( llGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point1_lon_label );
    llGrid->addWidget( point1_lon );
    ptGrid->addLayout( llGrid );

    ptlGrid = new QHBoxLayout();
    ptlGrid->addWidget( point2_label,2 );
    ptlGrid->addWidget( point2_getgps );
    ptGrid->addLayout( ptlGrid );
    xyGrid = new QHBoxLayout();
    xyGrid->addWidget( point2_x_label );
    xyGrid->addWidget( point2_x );
    xyGrid->addWidget( point2_y_label );
    xyGrid->addWidget( point2_y );
    ptGrid->addLayout( xyGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point2_lat_label );
    llGrid->addWidget( point2_lat );
    ptGrid->addLayout( llGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point2_lon_label );
    llGrid->addWidget( point2_lon );
    ptGrid->addLayout( llGrid );

    ptlGrid = new QHBoxLayout();
    ptlGrid->addWidget( point3_label,2 );
    ptlGrid->addWidget( point3_getgps );
    ptGrid->addLayout( ptlGrid );
    xyGrid = new QHBoxLayout();
    xyGrid->addWidget( point3_x_label );
    xyGrid->addWidget( point3_x );
    xyGrid->addWidget( point3_y_label );
    xyGrid->addWidget( point3_y );
    ptGrid->addLayout( xyGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point3_lat_label );
    llGrid->addWidget( point3_lat );
    ptGrid->addLayout( llGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point3_lon_label );
    llGrid->addWidget( point3_lon );
    ptGrid->addLayout( llGrid );

    pointsTab->setLayout( ptGrid );

    return grid;
}

QLayout* LayerMapConfig::createVertical()
{
    QVBoxLayout* grid = new QVBoxLayout();
    grid->addWidget( tabs );
    // setup tab
    if ( tab_setup->layout() )
        delete tab_setup->layout();
    QVBoxLayout* setupGrid = new QVBoxLayout();
    setupGrid->addWidget( title_label );
    setupGrid->addWidget( title );
    setupGrid->addWidget( description_label );
    setupGrid->addWidget( description );
  //  QHBoxLayout* btGrid = new QHBoxLayout();
    setupGrid->addWidget( import_ozical );
    setupGrid->addWidget( clear_cache );
    setupGrid->addWidget( rebuild_cache );
 //   setupGrid->addLayout( btGrid );
    setupGrid->addStretch();
    tab_setup->setLayout( setupGrid );

    // points tab
    if ( pointsTab->layout() )
        delete pointsTab->layout();
    QVBoxLayout* ptGrid = new QVBoxLayout();
    QHBoxLayout* ptlGrid = new QHBoxLayout();
    ptlGrid->addWidget( point1_label,2 );
    ptlGrid->addWidget( point1_getgps );
    ptGrid->addLayout( ptlGrid );
    QHBoxLayout* xyGrid = new QHBoxLayout();
    xyGrid->addWidget( point1_x_label );
    xyGrid->addWidget( point1_x );
    xyGrid->addWidget( point1_y_label );
    xyGrid->addWidget( point1_y );
    ptGrid->addLayout( xyGrid );
    QHBoxLayout* llGrid = new QHBoxLayout();
    llGrid->addWidget( point1_lat_label );
    llGrid->addWidget( point1_lat );
    ptGrid->addLayout( llGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point1_lon_label );
    llGrid->addWidget( point1_lon );
    ptGrid->addLayout( llGrid );

    ptlGrid = new QHBoxLayout();
    ptlGrid->addWidget( point2_label,2 );
    ptlGrid->addWidget( point2_getgps );
    ptGrid->addLayout( ptlGrid );
    xyGrid = new QHBoxLayout();
    xyGrid->addWidget( point2_x_label );
    xyGrid->addWidget( point2_x );
    xyGrid->addWidget( point2_y_label );
    xyGrid->addWidget( point2_y );
    ptGrid->addLayout( xyGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point2_lat_label );
    llGrid->addWidget( point2_lat );
    ptGrid->addLayout( llGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point2_lon_label );
    llGrid->addWidget( point2_lon );
    ptGrid->addLayout( llGrid );

    ptlGrid = new QHBoxLayout();
    ptlGrid->addWidget( point3_label,2 );
    ptlGrid->addWidget( point3_getgps );
    ptGrid->addLayout( ptlGrid );
    xyGrid = new QHBoxLayout();
    xyGrid->addWidget( point3_x_label );
    xyGrid->addWidget( point3_x );
    xyGrid->addWidget( point3_y_label );
    xyGrid->addWidget( point3_y );
    ptGrid->addLayout( xyGrid );
    llGrid = new QHBoxLayout();
    llGrid->addWidget( point3_lat_label );
    llGrid->addWidget( point3_lat );
    ptGrid->addLayout( llGrid );
    llGrid = new  QHBoxLayout();
    llGrid->addWidget( point3_lon_label );
    llGrid->addWidget( point3_lon );
    ptGrid->addLayout( llGrid );

    pointsTab->setLayout( ptGrid );

    return grid;

}

void LayerMapConfig::importCalibration()
{
    QString filename = FileNavigator::openCal();
    if ( (filename != "") )
    {
        QList<QPoint> new_pointsXY;
        QList<QPointF> new_pointsLL;
        bool calibrate = false;
        QString n;
        QString d;
        // 1) check if its out CAL file
        if ( !(calibrate = ( layer_map->loadCalibration( filename, new_pointsXY, new_pointsLL, n, d )) ) )
        {
            // 2) check if there is an Ozi explorer MAP file
            if ( !(calibrate = ( layer_map->loadOziMap( filename, new_pointsXY, new_pointsLL )) ) )
                // 3) check if there is an CompeGPS IMP file
                calibrate = layer_map->loadCompeImp( filename, new_pointsXY, new_pointsLL );
        }
        else
        {
            if ( QMessageBox::question( this,
                                     tr("Update title"),
                                     tr("Do you want to update title and description?"),
                                     QMessageBox::Yes|QMessageBox::No,
                                     QMessageBox::NoButton ) == QMessageBox::Yes )
            {
                description->setText( d );
                title->setText( n );
            }
        }

        // If we where successful, store the calibration!
        if ( calibrate )
        {
            point1_x->setText( QString("%1").arg(new_pointsXY.at(0).x()) );
            point1_y->setText( QString("%1").arg(new_pointsXY.at(0).y()) );
            point1_lon->setText( QString("%1").arg(new_pointsLL.at(0).x()) );
            point1_lat->setText( QString("%1").arg(new_pointsLL.at(0).y()) );

            point2_x->setText( QString("%1").arg(new_pointsXY.at(1).x()) );
            point2_y->setText( QString("%1").arg(new_pointsXY.at(1).y()) );
            point2_lon->setText( QString("%1").arg(new_pointsLL.at(1).x()) );
            point2_lat->setText( QString("%1").arg(new_pointsLL.at(1).y()) );

            point3_x->setText( QString("%1").arg(new_pointsXY.at(2).x()) );
            point3_y->setText( QString("%1").arg(new_pointsXY.at(2).y()) );
            point3_lon->setText( QString("%1").arg(new_pointsLL.at(2).x()) );
            point3_lat->setText( QString("%1").arg(new_pointsLL.at(2).y()) );
        }
        else
            QMessageBox::critical(0, tr("Load error"), tr("Unable to parse calibration file" ));
    }
}
